package pl.edu.agh.jemo.evolution.algorithm.impl;

import java.util.List;
import java.util.Random;

import javax.swing.JPanel;

import pl.edu.agh.jemo.conf.types.PrintableType;
import pl.edu.agh.jemo.evolution.algorithm.AbstractAlgorithm;
import pl.edu.agh.jemo.evolution.genotype.Genotype;
import pl.edu.agh.jemo.evolution.genotype.impl.DoubleGenotype;
import pl.edu.agh.jemo.evolution.specimen.Specimen;

public class ClusteringTestAlgorithm extends AbstractAlgorithm {
	private Random rand = new Random();

	@Override
	protected void endAlgorithm() {
	}

	@Override
	public JPanel getConfigPanel() {
		return null;
	}

	@Override
	protected void performInit() {
		System.out.println(rand.nextInt());
	}

	public Double generateRadius(Double radius) {
//		return Math.pow(rand.nextDouble(), 2.)*radius * ( rand.nextBoolean() ? 1. : -1.);
		return Math.pow(rand.nextDouble(), 2.)*radius;
	}
	
	@Override
	protected void step() {
		Double radius = getCurrentStep()/5.0; //dla 10 krokow
		population.clear();
		
		
		for(int i=0;i<populationSize/4;i++) {
			Specimen spec = new Specimen();
			try {
				Double fi;
				Double r;
				spec.init(population.getObjectiveFunctionSet(), DoubleGenotype.class);
				fi = rand.nextDouble() * 2. * Math.PI;
				r = generateRadius(radius);
				spec.getGenotype()[0].fromDouble(r*Math.cos(fi) + 1.); 
				spec.getGenotype()[1].fromDouble(r*Math.sin(fi) + 1.);
				spec.moveToDomain();
				population.add(spec);
				
				spec = new Specimen();
				fi = rand.nextDouble() * 2. * Math.PI;
				spec.init(population.getObjectiveFunctionSet(), DoubleGenotype.class);
				r = generateRadius(radius);
				spec.getGenotype()[0].fromDouble(r*Math.cos(fi) - 1.); 
				spec.getGenotype()[1].fromDouble(r*Math.sin(fi) - 1.);
				spec.moveToDomain();
				population.add(spec);
				
				spec = new Specimen();
				fi = rand.nextDouble() * 2. * Math.PI;
				spec.init(population.getObjectiveFunctionSet(), DoubleGenotype.class);
				r = generateRadius(radius);
				spec.getGenotype()[0].fromDouble(r*Math.cos(fi) + 1.); 
				spec.getGenotype()[1].fromDouble(r*Math.sin(fi) - 1.);
				spec.moveToDomain();
				population.add(spec);
				
				spec = new Specimen();
				fi = rand.nextDouble() * 2. * Math.PI;
				spec.init(population.getObjectiveFunctionSet(), DoubleGenotype.class);
				r = generateRadius(radius);
				spec.getGenotype()[0].fromDouble(r*Math.cos(fi) - 1.); 
				spec.getGenotype()[1].fromDouble(r*Math.sin(fi) + 1.);
				spec.moveToDomain();
				population.add(spec);
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		calculatePhenotype();
	}

	@Override
	public List<PrintableType<? extends Specimen>> validateSpecimenTypes(
			List<PrintableType<? extends Specimen>> specimenTypesList) {
		return specimenTypesList;
	}

}
